home *** CD-ROM | disk | FTP | other *** search
/ Collection of Tools & Utilities / Collection of Tools and Utilities.iso / asmutil / asm_n_z.zip / NEWINIT.ASM < prev    next >
Assembly Source File  |  1987-05-05  |  18KB  |  574 lines

  1. title newinit.asm
  2. comment |--------------------------------------------------------------
  3. In text modes the active page can be switched between 1-4 (80-col) or
  4.  1-8 (40-col) by pressing ALT and the corresponding # on the TOP ROW. This
  5.  feature can only be used to view the other pages.  Results of all CON I/O
  6.  while paging are unpredictable and messy.
  7. As protection against duplicate installation, INT 15h with AX = X'FF00'
  8.  returns AX = X'ABCD'.
  9. The keypad "5" key will toggle processing.  While paused,  a flashing,
  10.  highlighted "P" will appear in the lower-right corner (not graphics).
  11. If Numlock is on, shift-"5" is required.  If Alt or Ctrl are pressed, nothing
  12.  changes.  Scroll Lock, Caps Lock, and Ins are irrelevant.
  13. This program sets the video mode to 80 col monochrome.
  14. The enhanced keyboard can be toggled on/off with Alt-PrtSc, and a 1/8 sec
  15.  2000 Hz tone will sound when toggled on.  (The PrtSc modification cannot
  16.  be turned off.)
  17. NOTE: If both  shift keys are depressed at installation time, the
  18.  installation will be cancelled, with errorlevel set to X'AB'.
  19. ------------------------------------------------------------------------|
  20. bios_data    segment at 0040h
  21.     org    17h
  22. kb_flag    db    ?    ; keyboard status byte
  23. kb_flag_1    db    ?
  24.  
  25.     org    49h
  26. v_mode    db    ?    ; BIOS video mode
  27. v_width    db    ?    ; BIOS screen width
  28.  
  29.     org    62h
  30. v_page    db    ?    ; BIOS video page
  31. mystery_w    dw    ?    ; word used by pause routine
  32. mystery_b    db    ?    ; byte used by pause routine
  33. bios_data ends
  34.  
  35. cseg    segment
  36.     assume    cs:cseg
  37.     org    80h
  38. parm_cnt    db    ?    ; parameter count
  39. parm_data    db    ?    ; start of parameter data space
  40.     org    100h    ; .COM file
  41.  
  42. begin:    jmp    init_vectors    ; initialize and attach to DOS
  43.  
  44. ; addresses of video and keyboard I/O ROM routines
  45. prtsc    dd    0    ; INT 5
  46. kybd    dd    0    ; INT 9
  47. cass    dd    0    ; INT 15h
  48. kybd_io    dd    0    ; INT 16h
  49.  
  50. ; constants and segments
  51. bios_dat    dw    40h    ; bios_data segment
  52. mono_seg    dw    0b000h    ; segment of MGA
  53. color_seg    dw    0b800h    ; segment of CGA
  54. datatbl    db    2,3,0,1,6,4,5    ; scan-code to video mode data
  55. indicator equ "P"+256*10001111b    ; an highlighted, flashing "P"
  56. row equ 24            ; position of indicator for mono moniter
  57. col equ 79
  58. mono_point    equ 2*((row*80)+col)    ; offset in mono segment
  59.  
  60. ; variable data
  61. vdata    db    0    ; current video mode or page
  62. code_seg    dw    0    ; CS of resident routines
  63. graph_bit    db    0    ; flag to signal graphics mode
  64. toggle    db    1    ; enables/disables enhanced keyboard
  65.  
  66. prtsc_int:    sti        ; enable interrupts
  67.     push    ax    ; save regs
  68.     push    dx
  69.     mov    ah,2    ; read printer status
  70.     xor    dx,dx    ; zero DX - LPT1
  71.     int    17h    ; printer I/O
  72.     xor    ah,30h    ; check for OFFLINE
  73.     jnz    chk_shft    ; skip beep, prepare for exit
  74.     pop    dx
  75. no_dump:    pop    ax
  76.     iret
  77. chk_shft:    pop    dx
  78.     push    ds
  79.     mov    ds,bios_dat    ; set DS = X'40'
  80.     assume    ds:bios_data
  81.     test    kb_flag,00000010b    ; check for LEFT shift key
  82.     pop    ds    ; restore regs
  83.     jz    no_dump    ; skip screen dump if no LEFT shift
  84.     pop    ax
  85.     jmp    prtsc    ; print screen routine
  86.  
  87. calculate:    assume    ds:bios_data
  88.     xor    ax,ax    ; zero AX
  89.     xor    cx,cx    ; likewise
  90.     mov    al,v_width    ; AX = 00 width
  91.     mov    cl,v_page    ; save for later multiply
  92.     mov    bx,25    ; calculate offset into page
  93.     mul    bl
  94.     dec    ax    ; = (25*width)-1
  95.     shl    ax,1    ; MUL AX,2 - skip attribute bytes
  96.     mov    bx,ax    ; save in BX
  97.     mov    ax,2048    ; byte length of 40 column page
  98.     cmp    v_width,40    ; check for 40 column screen
  99.     je    multiply    ; if yes, leave AX alone
  100.     shl    ax,1    ; if no, change to 80 column offset
  101. multiply:    mul    cx    ; multiply by page number
  102.     add    bx,ax    ; sum buffer offset with page offset
  103.     mov    es,color_seg    ; load ES with CGA segment
  104.     assume    es:nothing
  105. skip_cga:    mov    cx,es:[bx]    ; save screen data in CX
  106.     mov word ptr es:[bx],indicator   ; store flashing "P" on screen
  107.  
  108. rejoin:    ; branch made if graphics mode - skip indicator
  109.  
  110.     mov    dx,mystery_w    ; load mystery word
  111.     add    dx,4    ; more mysterious code
  112.     mov    al,mystery_b    ; load mystery byte
  113.     out    dx,al    ; I have no clue what this does
  114.  
  115.     call    reset
  116.     or    kb_flag_1,00001000b    ; turn ctrl-num-lock on
  117.     sti        ; enable interrupts
  118. again:    test    kb_flag_1,00001000b    ; check if ctrl-num-lock on
  119.     jnz    again    ; if on, check again
  120.  
  121.     cli        ; disable interrupts (play it safe)
  122.     test    graph_bit,1    ; check if graphics mode
  123.     mov    graph_bit,0    ; reset graphics flag
  124.     jnz    skip_mov    ; skip restoration of screen data
  125.     mov    es:[bx],cx    ; restore screen data
  126. skip_mov:    pop    es    ; restore regs
  127.     pop    dx
  128.     pop    cx
  129.     pop    bx
  130.     pop    ds
  131.     pop    ax
  132.     iret
  133.  
  134. pause:    assume    ds:bios_data    ; DS set in FIVE: routine
  135.     push    bx    ; save BX (for active page)
  136.     push    cx    ; save CX to use as scratch register
  137.     push    dx
  138.     push    es
  139.     cmp    v_mode,4    ; check for text mode
  140.     jb    calculate    ; continue if yes
  141.     cmp    v_mode,7    ; check for monochrome buffer
  142.     jne    no_p    ; skip "P" if graphics
  143.     mov    es,cs:mono_seg    ; point ES to segment at 0b000h
  144.     mov    bx,mono_point    ; offset into monochrome segment
  145.     jmp short skip_cga    ; skip color setup
  146.  
  147. no_p:    mov    graph_bit,1    ; set graphics mode flag
  148.     jmp short rejoin    ; rejoin main code
  149.  
  150. yes:    and    kb_flag_1,11110111b    ; turn ctrl-num-lock off
  151.     call    reset    ; reset keyboard
  152.     pop    ds
  153.     pop    ax
  154.     iret
  155.  
  156.     assume    ds:nothing
  157. five:    push    ds    ; save data segment
  158.     mov    ds,cs:bios_dat    ; point to keyboard data
  159.     assume    ds:bios_data
  160.     test    kb_flag_1,00001000b    ; check if Ctrl-NumLock on
  161.     jnz    yes    ; if yes, unpause
  162.     mov    al,kb_flag    ; get shift key status byte
  163.     test    al,00001100b    ; check for Alt or Ctrl pressed
  164.     jnz    quit    ; exit if so
  165.     and    al,00100011b    ; isolate NumLock and Shift bits
  166.     jz    pause    ; if zero (none pressed) then go!
  167.     cmp    al,00100000b
  168.     ja    pause    ; both NumLock & Shift must be pressed
  169.             ; if not, then end
  170.     assume    ds:nothing
  171. quit:    pop    ds    ; restore regs
  172.     pop    ax
  173.     jmp    kybd    ; goto BIOS
  174.  
  175.     assume    ds:nothing
  176. ; intercepts INT 9
  177. kybd_int:    push    ax    ; save reg
  178.     in    al,60h    ; get scan code
  179.     cmp    al,37h    ; scan code of PrtSc key
  180.     je    tog_chk    ; check for Alt pressed before toggling
  181.     test    toggle,1    ; check if enhanced keyboard enabled
  182.     jz    off    ; if not, skip enhanced processing
  183.     cmp    al,4ch    ; scan code of keypad "5" ?
  184.     je    five    ; if yes, check further
  185.     cmp    al,46h    ; check for Scroll-Lock (Break) key
  186.     je    break    ; if so, look for Ctrl-Shift
  187. off:    pop    ax    ;  if not, restore reg and
  188.     jmp    kybd    ; goto BIOS
  189.  
  190. ; check for right-shift-Ctrl
  191. break:    push    ds    ; save reg
  192.     mov    ds,bios_dat    ; set DS to bios data segment
  193.     assume    ds:bios_data
  194.     test    kb_flag_1,00001000b    ; check if ctrl-num-lock on
  195.     jnz    quit    ; goto BIOS if yes
  196.     test    kb_flag,00000001b    ; right shift key pressed?
  197.     jz    quit
  198.     test    kb_flag,00000100b    ; check for Ctrl key pressed
  199.     jz    quit
  200.     call    reset
  201.     mov    ax,4ccah    ; DOS EXIT function 4C
  202.             ;  ErrorLevel = 202
  203.     int    21h
  204.     pop    ds    ; restore regs
  205.     pop    ax
  206.     iret        ; return from key interrupt
  207.  
  208. tog_chk:    push    ds    ; save DS
  209.     mov    ds,bios_dat    ; point DS to bios data segment
  210.     assume    ds:bios_data
  211.     test    kb_flag_1,00001000b    ; check for Ctrl-NumLock pause on
  212.     jnz    quit    ; goto BIOS if yes
  213.     test    kb_flag,00000111b    ; check for Ctrl or L/R shift pressed
  214.     jnz    quit    ; don't toggle if yes - send key to bios
  215.     test    kb_flag,00001000b    ; check for Alt pressed
  216.     jz    quit    ; don't toggle if no - send key to bios
  217.     xor    toggle,1    ; toggle
  218.     jz    skip_beep    ; skip beep if toggled off
  219.     push    cx    ; save count reg for delay
  220. ; beep
  221. ; Step 1 -- prepare the timer to receive its divisor
  222.     mov     al,0b6h    ; timer mode register signal
  223.     out     67,al    ; output to timer control port
  224. ; Step 2 -- send the divisor count to the timer
  225. ;   Divisor = (1,190,000 / desired frequency)
  226.     mov     ax,595    ; divisor for 2000 Hz
  227.     out     66,al    ; output low-order byte of divisor
  228.     mov     al,ah    ;  high-order byte to output reg
  229.     out     66,al    ; output high-order byte of divisor
  230. ; Step 3 -- turn on the two bits which activate the speaker, and the
  231. ;           timer's control of the speaker
  232.     in      al,97    ; get current bit settings - port 97
  233.     mov     ah,al    ; save port 97 to turn sound off
  234.     or      al,03    ; turn on last two bits
  235.     out     97,al    ;  send back the new value
  236.  
  237.     mov     cx,8000h    ; approx 1/8 second
  238. delay:    loop    delay    ; sounding tone while counting
  239.     mov     al,ah    ; restore original port 97
  240.     out     97,al    ; stop tone
  241.     pop     cx    ; restore count reg
  242.  
  243. skip_beep:    call    reset    ; reset kybd and interrupt controller
  244.     pop    ds    ; restore regs